#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
异常管理器

该模块提供了异常管理的核心功能，包括异常注册、查找、创建和全局异常处理配置。

创建时间: 2023-07-01
作者: Python Tools Team
"""

import sys
import threading
from typing import Dict, Type, Optional, Callable, Any, List, Union

from modules.logger import LogManager
from .exception_types import BaseAppException


class ExceptionManager:
    """
    异常管理器，用于管理应用程序中的异常
    
    该类实现了单例模式，提供了异常注册、查找、创建和全局异常处理配置等功能。
    """
    
    # 单例实例
    _instance = None
    _lock = threading.Lock()
    
    # 异常类型映射表
    _exception_registry: Dict[str, Type[BaseAppException]] = {}
    
    # 全局异常处理器
    _global_handlers: List[Callable[[Exception], bool]] = []
    
    # 默认日志记录器
    _logger = LogManager.get_both_logger(name="exception_manager")
    
    def __new__(cls):
        with cls._lock:
            if cls._instance is None:
                cls._instance = super(ExceptionManager, cls).__new__(cls)
                # 初始化全局异常处理
                cls._instance._setup_global_exception_handling()
            return cls._instance
    
    def __init__(self):
        # 单例模式，__init__可能被多次调用，但我们只需要初始化一次
        pass
    
    def register_exception(self, exception_class: Type[BaseAppException]) -> None:
        """
        注册异常类型
        
        Args:
            exception_class: 要注册的异常类，必须是BaseAppException的子类
        
        Raises:
            TypeError: 如果exception_class不是BaseAppException的子类
        """
        if not issubclass(exception_class, BaseAppException):
            raise TypeError(f"异常类 {exception_class.__name__} 必须是BaseAppException的子类")
        
        # 使用异常类名作为键
        self._exception_registry[exception_class.__name__] = exception_class
        self._logger.debug(f"已注册异常类型: {exception_class.__name__}")
    
    def get_exception_class(self, name: str) -> Optional[Type[BaseAppException]]:
        """
        根据名称获取异常类
        
        Args:
            name: 异常类名称
        
        Returns:
            Type[BaseAppException] or None: 找到的异常类，如果未找到则返回None
        """
        return self._exception_registry.get(name)
    
    def create_exception(
            self,
            name: str,
            message: str,
            code: Optional[int] = None,
            details: Optional[Dict[str, Any]] = None,
            cause: Optional[Exception] = None
    ) -> BaseAppException:
        """
        创建指定类型的异常实例
        
        Args:
            name: 异常类名称
            message: 异常消息
            code: 异常代码
            details: 异常详细信息
            cause: 导致此异常的原始异常
        
        Returns:
            BaseAppException: 创建的异常实例
        
        Raises:
            ValueError: 如果指定名称的异常类未注册
        """
        exception_class = self.get_exception_class(name)
        if exception_class is None:
            raise ValueError(f"未注册的异常类型: {name}")
        
        return exception_class(message=message, code=code, details=details, cause=cause)
    
    def register_global_handler(self, handler: Callable[[Exception], bool]) -> None:
        """
        注册全局异常处理器
        
        Args:
            handler: 异常处理函数，接收一个Exception参数，返回一个布尔值表示是否已处理异常
        """
        self._global_handlers.append(handler)
        self._logger.debug(f"已注册全局异常处理器: {handler.__name__}")
    
    def _global_exception_handler(self, exc_type, exc_value, exc_traceback):
        """
        全局未捕获异常处理器
        
        Args:
            exc_type: 异常类型
            exc_value: 异常值
            exc_traceback: 异常回溯
        
        Returns:
            bool: 是否已处理异常
        """
        # 忽略KeyboardInterrupt异常
        if issubclass(exc_type, KeyboardInterrupt):
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
            return True
        
        # 记录未捕获的异常
        self._logger.critical(
            "未捕获的异常",
            exc_info=(exc_type, exc_value, exc_traceback)
        )
        
        # 调用注册的全局处理器
        handled = False
        for handler in self._global_handlers:
            try:
                if handler(exc_value):
                    handled = True
                    break
            except Exception as e:
                self._logger.error(f"全局异常处理器 {handler.__name__} 执行失败: {str(e)}")
        
        # 如果没有处理器处理异常，则调用系统默认处理器
        if not handled:
            sys.__excepthook__(exc_type, exc_value, exc_traceback)
        
        return handled
    
    def _setup_global_exception_handling(self) -> None:
        """
        设置全局异常处理
        """
        sys.excepthook = self._global_exception_handler
        self._logger.debug("已设置全局异常处理")
    
    def get_all_registered_exceptions(self) -> Dict[str, Type[BaseAppException]]:
        """
        获取所有注册的异常类型
        
        Returns:
            Dict[str, Type[BaseAppException]]: 异常名称到异常类的映射
        """
        return self._exception_registry.copy()
    
    def set_logger(self, logger) -> None:
        """
        设置日志记录器
        
        Args:
            logger: 日志记录器对象
        """
        self._logger = logger
    
    @classmethod
    def get_instance(cls) -> 'ExceptionManager':
        """
        获取ExceptionManager的单例实例
        
        Returns:
            ExceptionManager: 单例实例
        """
        if cls._instance is None:
            return cls()
        return cls._instance


# 创建并导出单例实例
exception_manager = ExceptionManager()


def register_exception(exception_class: Type[BaseAppException]) -> Type[BaseAppException]:
    """
    异常注册装饰器，用于注册自定义异常类
    
    Args:
        exception_class: 要注册的异常类，必须是BaseAppException的子类
    
    Returns:
        Type[BaseAppException]: 注册后的异常类
    
    Examples:
        >>> @register_exception
        >>> class MyCustomException(BaseAppException):
        >>>     '''自定义异常'''
        >>>     default_code = 10001
    """
    exception_manager.register_exception(exception_class)
    return exception_class


def register_global_handler(handler: Callable[[Exception], bool]) -> Callable[[Exception], bool]:
    """
    全局异常处理器注册装饰器
    
    Args:
        handler: 异常处理函数，接收一个Exception参数，返回一个布尔值表示是否已处理异常
    
    Returns:
        Callable: 注册后的处理器函数
    
    Examples:
        >>> @register_global_handler
        >>> def handle_database_errors(exc):
        >>>     if isinstance(exc, DatabaseException):
        >>>         # 处理数据库异常
        >>>         return True
        >>>     return False
    """
    exception_manager.register_global_handler(handler)
    return handler


def create_exception(
        name: str,
        message: str,
        code: Optional[int] = None,
        details: Optional[Dict[str, Any]] = None,
        cause: Optional[Exception] = None
) -> BaseAppException:
    """
    创建指定类型的异常实例
    
    Args:
        name: 异常类名称
        message: 异常消息
        code: 异常代码
        details: 异常详细信息
        cause: 导致此异常的原始异常
    
    Returns:
        BaseAppException: 创建的异常实例
    
    Examples:
        >>> try:
        >>>     # 可能抛出异常的代码
        >>>     raise ValueError("无效的值")
        >>> except ValueError as e:
        >>>     # 转换为应用程序异常
        >>>     raise create_exception(
        >>>         "ValidationException",
        >>>         "输入验证失败",
        >>>         code=4001,
        >>>         details={"field": "username"},
        >>>         cause=e
        >>>     )
    """
    return exception_manager.create_exception(name, message, code, details, cause)